package com.sia.springcloud.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sia.springcloud.mapper.DeviceMapper;
import com.sia.springcloud.mapper.PointMapper;
import com.sia.springcloud.model.Device;
import com.sia.springcloud.model.Point;
import com.sia.springcloud.protocol.model.OpcuaDevice;
import com.sia.springcloud.service.IDeviceService;
import com.sia.springcloud.result.GridDataResult;
import com.sia.springcloud.result.ResultUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: Sirius
 * @Date: 2021/12/21 1:20
 * @Description: 通信协议设备服务层接口实现类
 * 主要提供的方法：添加设备、分页查询设备、根据微服务名称查询正在数采的设备、批量删除设备、修改指定设备
 */
@Service("DeviceService")
public class DeviceService extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private PointMapper pointMapper;

    /**
     * 添加设备
     *
     * @param device
     * @return
     */
    public String insertDevice(Device device) {
        // 检查设备对象的数据格式是否符合要求
        String checkData = checkDeviceData(device);
        if (!checkData.equals("ok")) {
            return ResultUtil.createSimpleFailureJson(checkData);
        }
        deviceMapper.insert(device);

        return ResultUtil.createSimpleSuccessJson("设备添加成功");
    }


    /**
     * 检查设备对象的数据格式是否符合要求
     *
     * @param device
     * @return
     */
    public String checkDeviceData(Device device) {
        if (null == device.getDeviceName() || device.getDeviceName().trim().equals("")) {
            return "设备名称不能为空";
        } else {
            if (!device.getDeviceName().matches("^[a-z0-9A-Z]+$") && !device.getDeviceName().matches("[0-9]*") && !device.getDeviceName().matches("^[A-Za-z]+$")) {
                return "设备名称只能包含数字及字母";
            }
        }
        if (null == device.getHost() || device.getHost().trim().equals("")) {
            return "设备ip不能为空";
        } else {
            if (!this.validIp("*.*.*.*", device.getHost())) {
                return "设备ip格式有误";
            }
        }
        if (null == device.getPort()) {
            return "端口号不能为空";
        }


        if (null == device.getConnectionLimit() || device.getConnectionLimit().equals("")) {
            return "重连次数不能为空";
        } else {

            if (device.getConnectionLimit() > 100) {
                return "重连次数不可大于100";
            }
        }

        if (null == device.getTimeout() || device.getTimeout().equals("")) {
            return "超时时间不能为空";
        } else {

            if (device.getTimeout() > 30000) {
                return "超时时间不可大于30000";
            }
        }

        //关于同一个设备是否可以添加两次还需要讨论，因为同一个设备可能有两种协议
        //List<ModbusDevice> l = modbusDeviceMapper.queryByCondition(device);
        //if (null != l && l.size() > 0) {
        //    return "该设备IP+端口已存在";
        //}
        return "ok";
    }


    /**
     * @return
     * @Author sgw
     * @Date 2020/9/6 13:52
     * @Param
     * @Description validlIP 校验ip是否有效
     **/
    public Boolean validIp(String validIP, String ip) {
        if (!StringUtils.hasText(validIP)) {
            return true;
        }
        validIP = validIP.trim();
        if (!StringUtils.hasText(ip)) {
            return false;
        }
        ip = ip.trim();
        String ipReg = "^((1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])|\\*)\\."
                + "((1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)|\\*)\\."
                + "((1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)|\\*)\\."
                + "((1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)|\\*)$";
        /**校验ip的格式*/
        Pattern pattern = Pattern.compile(ipReg);
        Matcher ipMatcher = pattern.matcher(ip);
        if (!ipMatcher.matches()) {
            return false;
        }
        /**validIP 的格式*/
        Pattern oriPattern = Pattern.compile(ipReg);
        Matcher oriMatcher = oriPattern.matcher(validIP);
        if (!oriMatcher.matches()) {
            return false;
        }
        /**validIP 相同*/
        if (validIP.equals(ip)) {
            return true;
        }
        /**校验ip是否处在validlIP段内*/
        String[] oriIpArr = validIP.split("\\.");
        String[] ipArr = ip.split("\\.");
        Boolean hasStar = false;
        String star = "*";
        for (int i = 0; i < oriIpArr.length; i++) {
            String oriIp = oriIpArr[i];
            boolean flag = oriIp.equals(star);
            if (flag) {
                hasStar = flag;
            }
            if (hasStar && !flag) {
                return false;
            }
            if (!ipArr[i].equals(oriIp) && !oriIp.equals(star)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 分页查询设备
     * <p>
     * start应该是页数
     * limit应该是每页的个数
     * total是总数量
     *
     * @param start
     * @param limit
     * @param protocolName
     * @return String
     */
    public String queryDevice(Integer start, Integer limit, String protocolName) {


        QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
        deviceQueryWrapper.eq("protocol_name", protocolName);
        Integer total = deviceMapper.selectCount(deviceQueryWrapper);

        Page<Device> devicePage = new Page<>();
        devicePage.setTotal(total);
        devicePage.setCurrent(start);
        devicePage.setSize(limit);

        IPage<Device> deviceIPage = deviceMapper.selectPage(devicePage, deviceQueryWrapper);
        List<Device> deviceList = deviceIPage.getRecords();

        ArrayList<OpcuaDevice> opcuaDeviceList = new ArrayList<>();

        deviceList.forEach(device -> {
            opcuaDeviceList.add(OpcuaDevice.reconvert(device));
        });

        GridDataResult<OpcuaDevice> deviceListResult = new GridDataResult<>();

        deviceListResult.setTotal(total);
        deviceListResult.setRoot(opcuaDeviceList);

        return JSON.toJSONString(deviceListResult);
    }



    /**
     * 批量删除设备
     * <p>
     * 首先根据DeviceId删除变量表中对应设备的变量，然后根据DeviceId删除设备表中的设备
     *
     * @param deviceIdList
     * @return
     */
    public String deleteDevice(String[] deviceIdList) {

        for (String deviceIdStr :deviceIdList) {
            int deviceId = Integer.parseInt(deviceIdStr);
            QueryWrapper<Point> pointQueryWrapper = new QueryWrapper<>();
            pointQueryWrapper.eq("device_id", deviceId);
            pointMapper.delete(pointQueryWrapper);

            deviceMapper.deleteById(deviceId);
        }
        return ResultUtil.createSimpleSuccessJson("设备信息删除成功");
    }


    /**
     * 根据id修改设备
     *
     * @param device
     * @return
     */
    public String updateDevice(Device device) {

        String checkData = this.checkDeviceData(device);
        if (!checkData.equals("ok")) {
            return ResultUtil.createSimpleFailureJson(checkData);
        }
        deviceMapper.updateById(device);
        return ResultUtil.createSimpleSuccessJson("设备修改成功");
    }


    /**
     * 获取设备表格格式
     *
     * @return
     */
    @Override
    public String tableStructure() {
        return null;
    }

}